import asyncio
import time

from bson import ObjectId
from openai import AsyncOpenAI  # 改为异步客户端
import logging
from typing import Dict, Any
from pymongo import MongoClient
from app.models.models import GeneratedComment
from datetime import datetime
from app.crud.generated_comment import GeneratedCommentCRUD
from app.crud.event import EventCRUD
from app.crud.generated_prompt import GeneratedPromptCRUD
from app.schemas.generate import GenerateCommentsWithNoDbRespond

logger = logging.getLogger(__name__)


class TextGenerationService:
    def __init__(self):
        # self.db = get_database()
        # self.crud = AnalysisCRUD(self.db)
        self.client = AsyncOpenAI(
                #openai
                # api_key="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",  # TODO 填入API

                # deepseek(官网渠道的并发似乎有些问题)
                # api_key="sk-d0f02fe402c14d8da341b0d19a4f0032",
                # base_url="https://api.deepseek.com"

                # siliconflow
                api_key="sk-ivqdsnrsoxvrylquqptzfeixapvccwvzqawmyrtsuyhijqza",
                base_url="https://api.siliconflow.cn/v1"
            )


    # async def generate_text(self, prompt: str, number: int) -> Dict[str, Any]:
    #     """
    #     按提示词与数量生成文本
    #
    #     Args:
    #         prompt (str): 文本生成提示词
    #         number (int): 需要生成的数量
    #
    #     Returns:
    #         Dict[str, Any]: 生成的文本与状态
    #     """
    #     try:
    #         # 最大并发数限制（建议根据API速率限制调整）
    #         MAX_CONCURRENT_REQUESTS = 5  # 例如：DeepSeek API允许的每秒最大请求数
    #         semaphore = asyncio.Semaphore(MAX_CONCURRENT_REQUESTS)
    #
    #         async def _make_single_request(request_idx: int) -> str:
    #             """单个请求的封装函数"""
    #             async with semaphore:  # 限制并发量
    #                 print(f"正在进行第 {request_idx + 1} / {number} 次请求")
    #                 start_time = time.time()
    #                 print(f"👉 请求 {request_idx} 开始 ({time.time() - start_time:.2f}s)")
    #
    #                 response = await self.client.chat.completions.create(
    #                     model="deepseek-chat",
    #                     messages=[
    #                         {
    #                             "role": "system",
    #                             "content": "假设你是一个真正的人在进行评论,面对给出的事件情景，你可以任选一种角度但只返回有且仅有一条评论，评论要像真人一样自然，但无论是长评论还是短评论，总字数一定要在100子以内。注意回复不要有多余的内容且只生成一条评论，直接回复评论内容即可"
    #                         },
    #                         {"role": "user", "content": prompt}
    #                     ],
    #                     # temperature=1.5,  # 高随机性
    #                     # top_p=0.9,  # 高多样性
    #                     # max_tokens=500,  # 生成长文本
    #                     # frequency_penalty=0.7,  # 减少重复
    #                     # presence_penalty=0.7,  # 增加新内容
    #                     stream=False
    #                 )
    #                 text = response.choices[0].message.content
    #                 print(f"🛑 请求 {request_idx} 结束 ({time.time() - start_time:.2f}s)")
    #                 print(text)
    #                 print("#################")
    #                 return text
    #
    #         # 并发执行所有请求
    #         tasks = [_make_single_request(i) for i in range(number)]
    #         generated_texts = await asyncio.gather(*tasks)
    #
    #         return {
    #             "status": "success",
    #             "generated_texts": generated_texts
    #         }
    #
    #     except Exception as e:
    #         logger.exception("Text generation failed")
    #         return {
    #             "status": "error",
    #             "message": f"Text generation failed: {str(e)}"
    #         }

    async def generate_comments(self, event_id: str, prompt_id: str, number: int, model_type: str, last_editor: str) -> Dict[
        str, Any]:
        """
        根据event_id和prompt_id生成指定数量的评论

        Args:
            event_id (str): 事件ID
            prompt_id (str): 提示词ID
            number (int): 生成评论的数量
            model_type (str): 模型类型
            last_editor (str): 最后编辑人ID

        Returns:
            Dict[str, Any]: 生成的评论与状态
        """
        try:
            # 从MongoDB中获取事件的描述和提示词文本
            event = await EventCRUD.get_event_by_id(event_id)
            prompt = await GeneratedPromptCRUD.get_prompt_by_id(prompt_id)
            
            if not event or not prompt:
                return {
                    "status": "error",
                    "message": "Event or prompt not found."
                }

            # 合并文本
            combined_text = f"以下是事件描述：{event['description']} ；；以下是期望生成的评论方向：{prompt['prompt_text']}"

            # 使用合并后的文本调用generate_text函数
            result = await self.generate_text(combined_text, number)
            if result['status'] != 'success':
                return result

            generated_texts = result['generated_texts']
            generated_comments=[]

            for i, generated_text in enumerate(generated_texts):
                # 创建GeneratedComment对象
                comment = GeneratedComment(
                    event_id=event_id,
                    prompt_id=prompt_id,
                    content=generated_text,
                    model_type=model_type,
                    last_editor=last_editor,
                    created_time=datetime.utcnow().isoformat(),
                    updated_time=datetime.utcnow().isoformat()
                )

                # 插入到MongoDB (移除await，因为PyMongo操作是同步的)
                GeneratedCommentCRUD.create_comment(comment.dict(by_alias=True))
                generated_comments.append(comment)

            return {
                "status": "success",
                "generated_comments": [comment.dict() for comment in generated_comments]
            }

        except Exception as e:
            logger.exception("Failed to generate comments")
            return {
                "status": "error",
                "message": f"Failed to generate comments: {str(e)}"
            }


    # async def get_generated_comments_by_event(self, event_id: str) -> Dict[str, Any]:
    #     """
    #     根据event_id获取所有GeneratedComment
    #
    #     Args:
    #         event_id (str): 事件ID
    #
    #     Returns:
    #         Dict[str, Any]: 查询结果
    #     """
    #     try:
    #         client = MongoClient('mongodb://localhost:27017/')
    #         db = client['public_sentiment']
    #         comments = list(await db.generated_comment.find({'event_id': event_id}))
    #         return {
    #             "status": "success",
    #             "comments": comments
    #         }
    #     except Exception as e:
    #         logger.exception("Failed to fetch comments")
    #         return {
    #             "status": "error",
    #             "message": f"Failed to fetch comments: {str(e)}"
    #         }
    #
    #
    # async def get_generation_prompts_by_event(self, event_id: str) -> Dict[str, Any]:
    #     """
    #     根据event_id获取所有GenerationPrompt
    #
    #     Args:
    #         event_id (str): 事件ID
    #
    #     Returns:
    #         Dict[str, Any]: 查询结果
    #     """
    #     try:
    #         client = MongoClient('mongodb://localhost:27017/')
    #         db = client['public_sentiment']
    #         prompts = list(await db.generation_prompt.find({'event_id': event_id}))
    #
    #         for prompt in prompts:
    #             prompt['_id'] = str(prompt['_id'])  # ObjectId → str
    #
    #         return {
    #             "status": "success",
    #             "prompts": prompts
    #         }
    #     except Exception as e:
    #         logger.exception("Failed to fetch prompts")
    #         return {
    #             "status": "error",
    #             "message": f"Failed to fetch prompts: {str(e)}"
    #         }
    #
    #
    # async def get_event_by_id(self, event_id: str) -> Dict[str, Any]:
    #     """
    #     根据event_id获取对应Event
    #
    #     Args:
    #         event_id (str): 事件ID
    #
    #     Returns:
    #         Dict[str, Any]: 查询结果
    #     """
    #     try:
    #         client = MongoClient('mongodb://localhost:27017/')
    #         db = client['public_sentiment']
    #         event = await db.event.find_one({'_id': ObjectId(event_id)})
    #         if event["_id"]:
    #             event["_id"] = str(event["_id"])
    #
    #         if event:
    #             return {
    #                 "status": "success",
    #                 "event": event
    #             }
    #         else:
    #             return {
    #                 "status": "error",
    #                 "message": "Event not found."
    #             }
    #     except Exception as e:
    #         logger.exception("Failed to fetch event")
    #         return {
    #             "status": "error",
    #             "message": f"Failed to fetch event: {str(e)}"
    #         }


    async def generate_single_text(self, prompt: str, request_idx: int) -> Dict[str, Any]:
        """
        按提示词生成单条文本

        Args:
            prompt (str): 文本生成提示词
            request_idx (int): 请求序号，用于日志记录

        Returns:
            Dict[str, Any]: 生成的文本与状态
        """
        try:
            start_time = time.time()
            print(f"👉 请求 {request_idx} 开始 ({time.strftime('%H:%M:%S')})")
            
            response = await self.client.chat.completions.create(
                # model="deepseek-chat",
                # model="gpt-4o-mini",
                model="Pro/deepseek-ai/DeepSeek-V3",

                messages=[
                    {
                        "role": "system",
                        "content": "假设你是一个真正的人在进行评论,面对给出的事件情景，你可以任选一种角度但只返回有且仅有一条评论，评论要像真人一样自然，但无论是长评论还是短评论，总字数一定要在100子以内。注意回复不要有多余的内容且只生成一条评论，直接回复评论内容即可"
                    },
                    {"role": "user", "content": prompt}
                ],
                stream=False
            )
            text = response.choices[0].message.content
            
            end_time = time.time()
            print(f"🛑 请求 {request_idx} 结束 ({time.strftime('%H:%M:%S')}) - 耗时: {end_time - start_time:.2f}秒")
            print(f"生成内容: {text}")
            print("#" * 50)
            
            return {
                "status": "success",
                "generated_text": text
            }

        except Exception as e:
            logger.exception(f"Text generation failed for request {request_idx}")
            return {
                "status": "error",
                "message": f"Text generation failed: {str(e)}"
            }

    async def generate_comments_with_no_db(self, prompt: str, number: int) -> Dict[str, Any]:
        """
        测试版
        直接通过提示词和数量进行评论生成，以及生成内容不插入数据库直接返回

        Args:
            prompt(str): 提示词
            number (int): 生成评论的数量

        Returns:
            Dict[str, Any]: 生成的评论与状态
        """
        try:
            total_start_time = time.time()
            print(f"\n开始批量生成评论 - 开始时间: {time.strftime('%H:%M:%S')}")
            print(f"总请求数量: {number}")
            print("-" * 50)
            
            # 创建多个并发任务
            tasks = [self.generate_single_text(prompt, i) for i in range(number)]
            
            # 并发执行所有请求
            results = await asyncio.gather(*tasks)
            
            generated_comments = []
            
            # 处理结果
            for result in results:
                if result['status'] != 'success':
                    continue
                    
                comment = GenerateCommentsWithNoDbRespond(
                    content=result['generated_text'],
                    created_time=datetime.utcnow().isoformat(),
                    updated_time=datetime.utcnow().isoformat()
                )
                generated_comments.append(comment)

            total_end_time = time.time()
            total_time = total_end_time - total_start_time
            print(f"\n批量生成评论完成 - 结束时间: {time.strftime('%H:%M:%S')}")
            print(f"总耗时: {total_time:.2f}秒")
            print(f"平均每条评论耗时: {total_time/number:.2f}秒")
            print("-" * 50)

            return {
                "status": "success",
                "generated_comments": [comment.dict() for comment in generated_comments]
            }

        except Exception as e:
            logger.exception("Failed to generate comments")
            return {
                "status": "error",
                "message": f"Failed to generate comments: {str(e)}"
            }

    async def generate_comments_to_db(self, prompt: str, number: int, event_id: str, model_type: str = "Pro/deepseek-ai/DeepSeek-V3", last_editor: str = None) -> Dict[str, Any]:
        """
        生成评论并存储到数据库

        Args:
            prompt (str): 提示词
            number (int): 需要生成的评论数量
            event_id (str): 事件ID
            model_type (str, optional): 模型类型. Defaults to "Pro/deepseek-ai/DeepSeek-V3".
            last_editor (str, optional): 最后编辑人. Defaults to None.

        Returns:
            Dict[str, Any]: 生成的评论与状态
        """
        try:
            total_start_time = time.time()
            print(f"\n开始批量生成评论并存储到数据库 - 开始时间: {time.strftime('%H:%M:%S')}")
            print(f"总请求数量: {number}")
            print("-" * 50)
            
            # 创建多个并发任务
            tasks = [self.generate_single_text(prompt, i) for i in range(number)]
            
            # 并发执行所有请求
            results = await asyncio.gather(*tasks)
            
            generated_comments = []
            current_time = datetime.utcnow().isoformat()
            
            # 处理结果并存储到数据库
            for result in results:
                if result['status'] != 'success':
                    continue
                    
                # 创建GeneratedComment对象
                comment = GeneratedComment(
                    event_id=event_id,
                    prompt=prompt,
                    content=result['generated_text'],
                    model_type=model_type,
                    last_editor=last_editor,
                    created_time=current_time,
                    updated_time=current_time
                )

                # 插入到MongoDB (移除await，因为PyMongo操作是同步的)
                GeneratedCommentCRUD.create_comment(comment.dict(by_alias=True))
                generated_comments.append(comment)

            total_end_time = time.time()
            total_time = total_end_time - total_start_time
            print(f"\n批量生成评论完成 - 结束时间: {time.strftime('%H:%M:%S')}")
            print(f"总耗时: {total_time:.2f}秒")
            print(f"平均每条评论耗时: {total_time/number:.2f}秒")
            print(f"成功生成并存储评论数: {len(generated_comments)}")
            print("-" * 50)

            return {
                "status": "success",
                "generated_comments": [comment.dict() for comment in generated_comments]
            }

        except Exception as e:
            logger.exception("Failed to generate and store comments")
            return {
                "status": "error",
                "message": f"Failed to generate and store comments: {str(e)}"
            }

